// --- Programme Arduino ---
// Copyright X. HINAULT - Créé le 11/04/2010
// www.mon-club-elec.fr 

//  Code sous licence GNU GPL : 
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License,
//  or any later version.
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//  You should have received a copy of the GNU General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
//  

// --- Circuit à réaliser ---
// Connexion série entre la carte Arduino et le PC (utilise les broches 0 et 1)  
// Connecter  sur la broche 2 la broche de données du capteur One Wire (Numérique)

#include <OneWire.h> // librairie pour capteur OneWire

// --- Déclaration des constantes ---
//28 26 EF BB 03 00 00 4E
//---- code des instructions du capteur
const int modeLecture=0xBE;
const int lancerMesure=0x44;

// --- constantes des broches ---

const int broche_OneWire=2; 
const int broche_lumiere=A0;

// --- Déclaration des variables globales ---
byte data[12]; // Tableau de 12 octets pour lecture des 9 registres de RAM et des 3 registres d'EEPROM du capteur One Wire
byte adresse[8]; // Tableau de 8 octets pour stockage du code d'adresse 64 bits du composant One Wire

float ma_tempetf=0.0; 

// --- Déclaration des objets utiles pour les fonctionnalités utilisées ---
OneWire  capteur(broche_OneWire);  // crée un objet One Wire sur la broche voulue
unsigned long curMillis;
unsigned long oldMillis = 0;
unsigned int sensorValue = 0;

int delais = 1000;

void setup()   
{ 
  Serial.begin(115200); // initialise connexion série à 115200 bauds
  // --- initialisation du capteur DS18B20 ------
  capteurInit(); // appel de la fonction d'initialisation du capteur - au début seulement 
  // prise en compte du premier capteur trouvé

} 

//*************** FONCTION LOOP = Boucle sans fin = coeur du programme *************
// la fonction loop() s'exécute sans fin en boucle aussi longtemps que l'Arduino est sous tension

void loop()
{ 
  
  curMillis = millis();

  if ( ( curMillis - oldMillis ) > delais )
  {
    sensorValue = analogRead(broche_lumiere); 
    ma_tempetf = capteurMesureTemp(); // appel de la fonction de mesure - renvoie une valeur float
    Serial.print( curMillis);
    Serial.print(",");
    Serial.print (ma_tempetf,2); 

    Serial.print(",");
    Serial.println( sensorValue);
    oldMillis = curMillis - ( curMillis % 1000);
  }

} 

//************************** fonction d'initialisation du capteur ****************
void capteurInit()
{
  Serial.println("**** Detection du capteur **** "); 

  while (capteur.search(adresse)== false) // tant qu'aucun nouveau capteur est détecté
  {
    // la fonction search renvoie la valeur FAUX si aucun élément 1-wire est trouvé. 
    Serial.println("** Aucun capteur 1-wire present sur la broche ! **"); // affiche message + saut de ligne
    delay (1000); // pause 1 seconde
  }

  //la suite est exécutée seulement si un capteur est détecté

  // la fonction search renvoie la valeur VRAI si un élément 1-wire est trouvé. 
  // Stocke son code d'adresse 16 bits dans le tableau adresse[8]
  // adresse envoyé à la fonction correspond à l'adresse de début du tableau adresse[8] déclaré ...   

  Serial.print ("** 1 capteur 1-wire present avec code adresse 64 bits : ");


  //--- affichage des 64 bits d'adresse au format hexadécimal
   for(int i = 0; i < 8; i++) { // l'adresse renvoyée par la fonction search est stockée sur 8 octets

    if (adresse[i]<16) Serial.print('0'); // pour affichage des O poids fort au format hexadécimal
    Serial.print(adresse[i], HEX); // affiche 1 à 1 les 8 octets du tableau adresse au format hexadécimal
    Serial.print(" ");
  }

  Serial.println(" **"); 

  //---- test du type de capteur ---- 
  // le type du capteur est donné par le 1er octet du code adresse 64 bits
  // Valeur 0x28 pour capteur type DS18B20, 0x10 pour type DS18S20, 0x22 pour type DS1820
  if (adresse[0]==0x28) 
  { 
    Serial.println ("** Type du capteur present : Capteur temperature DS18B20. **");
  }
  else
  {
    Serial.println ("** Le capteur present n'est pas un capteur de temperature DS18B20. **");
  }


  //----- contrôle du code CRC ----
  // le dernier octet de l'adresse 64bits est un code de contrôle CRC 
  // à l'aide de la fonction crc8 on peut vérifier si ce code est valide
  if (capteur.crc8( adresse, 7) == adresse[7]) // vérification validité code CRC de l'adresse 64 bits
  // le code CRC de l'adresse 64 bits est le 8ème octet de l'adresse (index 7 du tableau)
  {
    Serial.println ("** Verification du code CRC de l'adresse 64 bits de ce capteur : VALIDE ! **"); 
  }
  else
  {
    Serial.println ("** Verification du code CRC de l'adresse 64 bits de ce capteur : NON VALIDE ! **");     
  }

  //------- message final détection ---- 
  Serial.println("***** fin de la recherche du capteur *****"); 

}
//----------- fin de la fonction d'initialisation du capteur ---------- 


//-------------- fonction de mesure de la température --------------- 

float capteurMesureTemp() 
{ 
   //-------- variable locale de la fonction ---------- 
  int tempet=0; // variable pour resultat brute  de la mesure
  float tempetf=0.0; // variable pour resultat à virgule de la mesure
 // Serial.println("**** Acquisition d'une mesure de la temperature **** "); 

  // avant chaque nouvelle instruction, il faut : 
  //    * initialiser le bus 1-wire
  //    * sélectionner le capteur détecté
  //    * envoyer l'instruction 

  //--------- lancer une mesure --------
  capteur.reset(); // initialise le bus 1-wire avant la communication avec un capteur donné
  capteur.select(adresse); // sélectionne le capteur ayant l'adresse 64 bits contenue dans le tableau envoyé à la fonction
  capteur.write(lancerMesure,1); // lance la mesure et alimente le capteur par la broche de donnée

  //-------- pause d'une seconde ----- 
  delay(1000);     // au moins 750 ms
  // il faudrait mettre une instruction capteur.depower ici, mais le reset va le faire

  //---------- passer en mode LECTURE ------------- 
  capteur.reset(); // initialise le bus 1-wire avant la communication avec un capteur donné
  capteur.select(adresse); // sélectionne le capteur ayant l'adresse 64 bits contenue dans le tableau envoyé à la fonction
  capteur.write(modeLecture,1); // passe en mode lecture de la RAM du capteur

  // ----------- lire les 9 octets de la RAM (appelé Scratchpad) ----

  for ( int i = 0; i < 9; i++) {           // 9 octets de RAM stockés dans 9 octets
    data[i] = capteur.read();             // lecture de l'octet de rang i stocké dans tableau data
  }
  //----- caclul de la température mesurée (enfin!) ---------

  data[1]=data[1] & B10000111; // met à 0 les bits de signes inutiles
  tempet=data[1]; // bits de poids fort
  tempet=tempet<<8; 
  tempet=tempet+data[0]; // bits de poids faible

  // --- en mode 12 bits, la résolution est de 0.0625°C - cf datasheet DS18B20
  tempetf=float(tempet)*6.25;
  tempetf=tempetf/100.0;

  return (tempetf);

}

// --- Fin programme ---
